<?php

namespace Framework\auth;
use Framework\auth\bean\JwtTokenConfigBean;
use Framework\auth\bean\JwtTokenResult;
use Framework\auth\bean\RedisConfigBean;
use Framework\auth\exceptions\JwtException;
use Framework\auth\interfaces\JwtTokenInterface;
use Framework\utils\Random;
use Framework\utils\StringUtil;

/**
 * Class JwtToken
 * @package Framework\auth
 * @author 飞鸟与鱼
 */
class JwtToken implements JwtTokenInterface
{
    /**
     * @var \Redis
     */
    protected $redisIntance;

    /**
     * @var \Framework\auth\bean\JwtTokenConfigBean
     */
    protected $jwtConfig;

    // 用户身份类型标识
    const USER_IDENTITY = "user";

    // 游客身份类型标识
    const VISITOR_IDENTITY = "visitor";

    public function __construct(RedisConfigBean $redisConfigBean, JwtTokenConfigBean $jwtTokenConfigBean)
    {
        $this->redisIntance = RedisInstance::getInstance($redisConfigBean);
        $this->jwtConfig = $jwtTokenConfigBean;
    }

    public function set($user_id)
    {
        if ($this->jwtConfig->isSso() && $this->check($user_id)){
            $this->clearInfo($user_id);
        }
        $token = Random::uuid();
        $this->redisIntance->set($this->jwtConfig->getTokenPrefixKey().$token, $user_id);
        $this->redisIntance->expire($this->jwtConfig->getTokenPrefixKey().$token, $this->jwtConfig->getExpire());
        $this->redisIntance->hMSet($this->jwtConfig->getInfoPrefixKey().$user_id, $this->getTokenInfo($token) );
        return $token;
    }

    public function get($token)
    {
        $resultBean = new JwtTokenResult();
        $user_id = $this->redisIntance->get($this->jwtConfig->getTokenPrefixKey().$token);
        if (empty($user_id)){
            if ($this->hasSso($token)){
                $this->redisIntance->del($this->jwtConfig->getTokenSsoKey().$token);
                throw new JwtException("账号已在其它设备登陆", -10002);
            }else{
                $visitor = $this->redisIntance->hGetAll($this->jwtConfig->getVistorKey().$token);
                if ($this->jwtConfig->isVistor() && !empty($visitor)){
                    $resultBean->setIdentity(JwtToken::VISITOR_IDENTITY);
                    $resultBean->setId(0);
                    $resultBean->setData($visitor);
                    return $resultBean;
                }
                throw new JwtException("账号未登录", -10001);
            }
        }
        $resultBean->setIdentity(JwtToken::USER_IDENTITY);
        $resultBean->setId($user_id);
        return $resultBean;
    }

    public function delete($key)
    {
    }

    public function check($user_id)
    {
        return !empty(
            $this->redisIntance->hGetAll($this->jwtConfig->getInfoPrefixKey().$user_id)
        );
    }

    public function getTokenInfo($token)
    {
        return [
            'token' => $token,
            'login_time' => time()
        ];
    }

    /**
     * 检测当前是否被顶替登录
     * @param $token
     * @return bool
     */
    public function hasSso($token)
    {
        return !empty(
            $this->redisIntance->get($this->jwtConfig->getTokenSsoKey().$token)
        );
    }


    /**
     * 清除原有用户Token信息
     * @param $user_id
     */
    private function clearInfo($user_id)
    {
        $token = $this->redisIntance->hGet($this->jwtConfig->getInfoPrefixKey().$user_id, 'token');
        $this->redisIntance->del($this->jwtConfig->getTokenPrefixKey().$token);
        $this->redisIntance->set($this->jwtConfig->getTokenSsoKey().$token, '1');
    }

    /**
     * 游客
     */
    public function handleVisitor()
    {
        $token = Random::uuid();
        $this->redisIntance->hMSet($this->jwtConfig->getVistorKey().$token, $this->jwtConfig->getVistorData());
        return $token;
    }
}